سیستم تحلیل داده‌های آکادمیک
پروژه داده‌کاوی

1 بارگذاری داده‌ها و کتابخانه‌های مورد نیاز

1.1 بارگذاری کتابخانه‌های R

اولین قدم، بارگذاری کتابخانه‌های لازم و بررسی اولیه داده‌ها برای درک ساختار، کیفیت و ویژگی‌های آماری آن است.

library(caret)
library(dplyr)
library(skimr)
library(rpart)
library(rpart.plot)
library(randomForest)
library(ggplot2)
library(patchwork)
library(forcats)
library(DT)

نقش هر کتابخانه در این پروژه:

ما از dplyr و ggplot2 به عنوان ابزارهای اصلی برای آماده‌سازی و نمایش داده‌ها استفاده می‌کنیم. در قلب فرآیند یادگیری ماشین، کتابخانه caret قرار دارد که وظیفه تقسیم داده‌ها و مدیریت آموزش مدل را بر عهده دارد.

برای مدل‌سازی، از rpart (برای درخت تصمیم تک) و randomForest (برای روش گروهی) بهره می‌بریم. همچنین برای درک سریع وضعیت آماری داده‌ها در شروع کار، از کتابخانه قدرتمند skimr استفاده شده است.

1.2 بارگذاری دیتاست

mis <- as.data.frame(read.csv(file.choose(), header = TRUE))

تشریح نحوه بارگذاری:
دستور read.csv تابع اصلی R برای خواندن فایل‌های متنی با جداکننده کاما است. استفاده از تابع file.choose() در داخل آن، یک پنجره محاوره‌ای باز می‌کند تا شما بتوانید فایل را به صورت تعاملی از سیستم خود انتخاب کنید.
همچنین آرگومان header = TRUE به برنامه اعلام می‌کند که سطر اول فایل شامل نام ستون‌ها (Variables) است و نباید به عنوان داده محاسباتی در نظر گرفته شود.

2 پیش‌پردازش داده‌ها

2.1 آمار توصیفی

str(mis)
## 'data.frame':    397 obs. of  7 variables:
##  $ X            : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ rank         : chr  "Prof" "Prof" "AsstProf" "Prof" ...
##  $ discipline   : chr  "B" "B" "B" "B" ...
##  $ yrs.since.phd: int  19 20 4 45 40 6 30 45 21 18 ...
##  $ yrs.service  : int  18 16 3 39 41 6 23 45 20 18 ...
##  $ sex          : chr  "Male" "Male" "Male" "Male" ...
##  $ salary       : int  139750 173200 79750 115000 NA 97000 175000 147765 119250 129000 ...
summary(mis)
##        X           rank            discipline        yrs.since.phd  
##  Min.   :  1   Length:397         Length:397         Min.   : 1.00  
##  1st Qu.:100   Class :character   Class :character   1st Qu.:12.00  
##  Median :199   Mode  :character   Mode  :character   Median :21.00  
##  Mean   :199                                         Mean   :22.32  
##  3rd Qu.:298                                         3rd Qu.:32.00  
##  Max.   :397                                         Max.   :56.00  
##                                                      NA's   :3      
##   yrs.service        sex                salary      
##  Min.   : 0.00   Length:397         Min.   : 57800  
##  1st Qu.: 7.00   Class :character   1st Qu.: 91000  
##  Median :16.00   Mode  :character   Median :107200  
##  Mean   :17.56                      Mean   :113698  
##  3rd Qu.:26.25                      3rd Qu.:134368  
##  Max.   :60.00                      Max.   :231545  
##  NA's   :5                          NA's   :6
skim(mis)
Data summary
Name mis
Number of rows 397
Number of columns 7
_______________________
Column type frequency:
character 3
numeric 4
________________________
Group variables None

Variable type: character

skim_variable n_missing complete_rate min max empty n_unique whitespace
rank 3 0.99 4 9 0 3 0
discipline 10 0.97 1 1 0 2 0
sex 5 0.99 4 6 0 2 0

Variable type: numeric

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
X 0 1.00 199.00 114.75 1 100 199 298.00 397 ▇▇▇▇▇
yrs.since.phd 3 0.99 22.32 12.93 1 12 21 32.00 56 ▇▇▆▅▁
yrs.service 5 0.99 17.56 12.91 0 7 16 26.25 60 ▇▅▃▂▁
salary 6 0.98 113698.21 30425.73 57800 91000 107200 134367.50 231545 ▆▇▅▂▁
mis$X <- NULL
datatable(head(mis, 100),
          options = list(
            scrollX = TRUE,
            pageLength = 5,
            dom = 'Bfrtip',
            language = list(url = '//cdn.datatables.net/plug-ins/1.10.11/i18n/Persian.json')
          ),
          caption = "جدول ۱: نمای کلی دیتاست اعضای هیئت علمی",
          rownames = FALSE,
          class = 'cell-border stripe hover'
)

یافته‌های حاصل از بررسی ساختار داده‌ها:

  • دستور str(mis): ابعاد دقیق داده‌ها (۳۹۷ مشاهده و ۷ متغیر) و نوع داده‌ها (مانند Integer برای اعداد و Factor برای دسته‌ها) را مشخص کرد.
  • دستور summary(mis): آماره‌های توصیفی کلیدی شامل میانگین، میانه، کمینه/بیشینه و چارک‌ها را محاسبه کرد که دید خوبی از توزیع متغیرهای عددی می‌دهد.
  • دستور skim(mis): این تابع قدرتمند، علاوه بر آمارهای پایه، وضعیت داده‌های گمشده (Missing Values) را به تفکیک هر ستون گزارش داد.
  • اقدام اصلاحی mis$X <- NULL: ستون X که صرفاً یک شمارنده ردیف (Index) وارد شده از فایل CSV بود و ارزش تحلیلی برای مدل‌سازی نداشت، از دیتاست حذف گردید.

2.2 مصورسازی داده‌ها

مصورسازی به ما کمک می‌کند تا الگوها، روابط، مقادیر پرت و توزیع داده‌ها را بهتر درک کنیم.

par(mfrow = c(1, 4))
boxplot(mis$yrs.since.phd)
boxplot(mis$yrs.service)
boxplot(mis$salary)
boxplot(mis$salary ~ mis$rank)

par(mfrow = c(1, 3))
barplot(table(mis$rank))
barplot(table(mis$discipline))
barplot(table(mis$sex))

histogram(mis$yrs.since.phd)

histogram(mis$yrs.service)

histogram(mis$salary)

تحلیل الگوهای بصری و آماری:
بررسی نمودارها حقایق مهمی را درباره ساختار داده‌ها آشکار کرد:

  • عدم توازن (Imbalance): داده‌ها در متغیرهای دسته‌ای سوگیری دارند؛ به طوری که اکثریت نمونه‌ها را رتبه «استاد تمام» (Prof) و جنسیت «مرد» تشکیل می‌دهند.
  • همبستگی کلیدی: نمودار جعبه‌ای salary ~ rank یک رابطه مستقیم و بسیار قوی را نشان می‌دهد. با ارتقای رتبه، میانه حقوق جهش قابل توجهی دارد؛ این ویژگی، salary را به یک پیش‌بینی‌کننده قدرتمند برای مدل تبدیل می‌کند.
  • توزیع متغیرهای عددی:
    • متغیر yrs.since.phd: توزیعی نسبتاً متقارن (شبه‌نرمال) دارد و اوج تراکم داده‌ها در بازه ۱۵ تا ۲۵ سال است.
    • متغیر yrs.service: دارای چولگی به راست (Right-skewed) است، به این معنی که اکثر اساتید سابقه خدمت کمتر از ۲۵ سال دارند.
    • متغیر salary: چولگی شدید به راست دارد. تمرکز اصلی حقوق‌ها در بازه ۹۰ تا ۱۱۰ هزار دلار است و وجود داده‌های پرت (Outliers) در حقوق‌های بالا کاملاً مشهود است.

2.3 پاکسازی داده‌ها

استراتژی مدیریت داده‌های گمشده (Missing Values):
تحلیل‌ها نشان می‌دهد حدود ۱۵٪ از داده‌ها در متغیرهای salary و discipline مفقود هستند. در این مرحله تصمیم‌گیری به شرح زیر انجام شد:

  • قابلیت مدل: اگرچه مدل‌های درختی (مانند rpart) می‌توانند با استفاده از تکنیک «Surrogate Splits» مقادیر گمشده را مدیریت کنند، ما از این قابلیت صرف‌نظر کردیم.
  • رویکرد انتخابی: ما روش حذف کامل ردیف (Listwise Deletion) را انتخاب کردیم.
  • استدلال و ریسک: دلیل اصلی این انتخاب، ساده‌سازی تحلیل و سازگاری با توابع ارزیابی استاندارد مانند caret::confusionMatrix است که با مقادیر NA دچار خطا می‌شوند.
    هشدار: باید آگاه باشیم که این روش در صورتی که داده‌ها به طور تصادفی گم نشده باشند، می‌تواند باعث ایجاد اریبی (Bias) در نتایج نهایی شود.
mis <- mis %>% mutate(rank = as.factor(rank),discipline = as.factor(discipline),sex = as.factor(sex)) %>% na.omit() 

گام‌های اجرایی پیش‌پردازش (Preprocessing Steps):

  • تبدیل نوع داده (Feature Encoding): با استفاده از دستور mutate، ستون‌های متنی (rank, discipline, sex) به ساختار Factor تبدیل شدند. این تبدیل برای R ضروری است تا بتواند سطوح (Levels) مختلف متغیرهای کیفی را در مدل‌سازی لحاظ کند.
  • پاکسازی داده‌ها (Data Cleaning): با دستور na.omit، استراتژی حذف کامل اعمال شد. این تابع کل دیتافریم را اسکن کرده و هر ردیفی را که حاوی حتی یک مقدار گم‌شده (NA) باشد، حذف می‌کند.

2.4 استدلال‌های فنی در مدیریت داده‌ها

2.4.1 ۱. مدیریت داده‌های پرت (Outliers Handling)

  • مشاهده: نمودارهای جعبه‌ای وجود مقادیر پرت در متغیرهای salary و yrs.service را نشان دادند.
  • تحلیل فنی: مدل‌های مبتنی بر درخت (مانند CART) ذاتاً نسبت به داده‌های پرت مقاوم (Robust) هستند. مکانیزم درخت بر اساس “آستانه‌های تقسیم” (Splitting Thresholds) کار می‌کند، نه میانگین یا واریانس. بنابراین، یک داده پرت (مثلاً حقوق بسیار بالا) صرفاً در یک سمتِ شرط قرار می‌گیرد و ساختار کلی مدل را منحرف نمی‌کند.
  • اقدام نهایی: داده‌های پرت حفظ شدند و تغییری در آن‌ها ایجاد نشد.

2.4.2 ۲. مقیاس‌بندی ویژگی‌ها (Feature Scaling)

  • تحلیل فنی: استانداردسازی (Standardization) یا نرمال‌سازی (Normalization) برای مدل‌هایی که بر اساس “فاصله اقلیدسی” کار می‌کنند (مانند KNN، SVM یا رگرسیون لجستیک) حیاتی است. اما در مدل‌های درختی، مقیاس اعداد تأثیری بر “خلوص گره‌ها” (Gini Impurity) یا انتخاب بهترین نقطه برش ندارد.
  • اقدام نهایی: از آنجا که برای درخت تصمیم غیرضروری است، این مرحله نادیده گرفته شد (Skipped). ## ساخت مدل پیش‌بینی

2.5 تقسیم داده به مجموعه آموزشی و آزمایشی

set.seed(38712)
index <- createDataPartition(mis$rank, p = 0.75, list = FALSE)
train <- mis[index, ]
test <- mis[-index, ]
dim(train)
## [1] 275   6
dim(test)
## [1] 90  6

تشریح فرآیند تقسیم‌بندی داده‌ها (Data Splitting):

  • تکرارپذیری (Reproducibility): دستور set.seed تضمین می‌کند که اعداد تصادفی تولید شده در هر بار اجرای کد، یکسان باشند. این کار برای استناد به نتایج علمی ضروری است.
  • نمونه‌گیری طبقه‌ای (Stratified Sampling): تابع createDataPartition به جای انتخاب تصادفی ساده، نسبت توزیع متغیر هدف (Rank) را در هر دو دسته حفظ می‌کند. یعنی اگر ۱۰٪ داده‌ها “دانشیار” هستند، در داده‌های آموزشی و آزمایشی نیز همین ۱۰٪ حفظ می‌شود.
  • نسبت تقسیم: داده‌ها به دو بخش آموزشی (۷۵٪) برای ساخت مدل و آزمایشی (۲۵٪) برای سنجش نهایی تقسیم شدند.

2.6 پیاده‌سازی الگوریتم درخت تصمیم (CART)

در این مرحله، ما از الگوریتم rpart (Recursive Partitioning and Regression Trees) برای ساخت مدل طبقه‌بندی استفاده می‌کنیم. هدف این است که قوانینی استخراج کنیم که بتوانند بر اساس ویژگی‌های موجود، رتبه علمی (Rank) را پیش‌بینی کنند.

تنظیمات ساخت مدل (Model Specification):

  • فرمول rank ~ .: این نحوه نوشتار در R به مدل می‌گوید که rank متغیر هدف (Target) است و نقطه (.) به معنی “تمام ستون‌های دیگر موجود در دیتاست” به عنوان متغیرهای پیش‌بینی‌کننده (Predictors) است.
  • آرگومان method = “class”: از آنجا که متغیر هدف ما کیفی (Categorical) است، این پارامتر به الگوریتم دستور می‌دهد که درخت را به صورت طبقه‌بندی (Classification) بسازد و نه رگرسیون.
  • داده‌ها: مدل صرفاً روی داده‌های train آموزش می‌بیند تا بعداً بتوانیم آن را با داده‌های test محک بزنیم.
model <- rpart(rank ~ ., data = train, method = "class")
summary(model)
## Call:
## rpart(formula = rank ~ ., data = train, method = "class")
##   n= 275 
## 
##           CP nsplit rel error   xerror       xstd
## 1 0.48387097      0 1.0000000 1.000000 0.08435831
## 2 0.20430108      1 0.5161290 0.516129 0.06768372
## 3 0.05376344      2 0.3118280 0.311828 0.05476679
## 4 0.01000000      3 0.2580645 0.311828 0.05476679
## 
## Variable importance
## yrs.since.phd   yrs.service        salary 
##            42            33            25 
## 
## Node number 1: 275 observations,    complexity param=0.483871
##   predicted class=Prof       expected loss=0.3381818  P(node) =1
##     class counts:    47    46   182
##    probabilities: 0.171 0.167 0.662 
##   left son=2 (69 obs) right son=3 (206 obs)
##   Primary splits:
##       yrs.since.phd < 11.5  to the left,  improve=63.585430, (0 missing)
##       yrs.service   < 5.5   to the left,  improve=47.413630, (0 missing)
##       salary        < 92850 to the left,  improve=43.301910, (0 missing)
##       sex           splits as  LR,        improve= 3.398741, (0 missing)
##       discipline    splits as  RL,        improve= 1.274892, (0 missing)
##   Surrogate splits:
##       yrs.service < 5.5   to the left,  agree=0.887, adj=0.551, (0 split)
##       salary      < 92025 to the left,  agree=0.836, adj=0.348, (0 split)
## 
## Node number 2: 69 observations,    complexity param=0.2043011
##   predicted class=AsstProf   expected loss=0.3333333  P(node) =0.2509091
##     class counts:    22    46     1
##    probabilities: 0.319 0.667 0.014 
##   left son=4 (22 obs) right son=5 (47 obs)
##   Primary splits:
##       yrs.service   < 5.5   to the right, improve=23.74729000, (0 missing)
##       salary        < 94054 to the right, improve=14.09444000, (0 missing)
##       yrs.since.phd < 8.5   to the right, improve=14.07374000, (0 missing)
##       sex           splits as  RL,        improve= 0.37553430, (0 missing)
##       discipline    splits as  RL,        improve= 0.09879227, (0 missing)
##   Surrogate splits:
##       yrs.since.phd < 8.5   to the right, agree=0.855, adj=0.545, (0 split)
##       salary        < 94054 to the right, agree=0.855, adj=0.545, (0 split)
## 
## Node number 3: 206 observations,    complexity param=0.05376344
##   predicted class=Prof       expected loss=0.1213592  P(node) =0.7490909
##     class counts:    25     0   181
##    probabilities: 0.121 0.000 0.879 
##   left son=6 (17 obs) right son=7 (189 obs)
##   Primary splits:
##       salary        < 87025 to the left,  improve=10.24141000, (0 missing)
##       yrs.since.phd < 13.5  to the left,  improve= 6.35139400, (0 missing)
##       yrs.service   < 10.5  to the left,  improve= 3.23197000, (0 missing)
##       sex           splits as  LR,        improve= 2.82329200, (0 missing)
##       discipline    splits as  RL,        improve= 0.07381862, (0 missing)
##   Surrogate splits:
##       yrs.since.phd < 48.5  to the right, agree=0.927, adj=0.118, (0 split)
##       yrs.service   < 48.5  to the right, agree=0.927, adj=0.118, (0 split)
## 
## Node number 4: 22 observations
##   predicted class=AssocProf  expected loss=0.09090909  P(node) =0.08
##     class counts:    20     1     1
##    probabilities: 0.909 0.045 0.045 
## 
## Node number 5: 47 observations
##   predicted class=AsstProf   expected loss=0.04255319  P(node) =0.1709091
##     class counts:     2    45     0
##    probabilities: 0.043 0.957 0.000 
## 
## Node number 6: 17 observations
##   predicted class=AssocProf  expected loss=0.3529412  P(node) =0.06181818
##     class counts:    11     0     6
##    probabilities: 0.647 0.000 0.353 
## 
## Node number 7: 189 observations
##   predicted class=Prof       expected loss=0.07407407  P(node) =0.6872727
##     class counts:    14     0   175
##    probabilities: 0.074 0.000 0.926
rpart.plot(model)

# مدل بدون هرس
model1 <- rpart(rank ~ ., data = train, method = "class",
                control = rpart.control(minsplit = 5, cp = 0))
rpart.plot(model1)

تحلیل خروجی مدل اولیه (Unpruned Tree):

  • اهمیت متغیرها (Variable Importance): نتایج نشان می‌دهد که دو متغیر yrs.since.phd (سال‌های پس از دکترا) و yrs.service (سابقه خدمت) با فاصله زیاد، تأثیرگذارترین عوامل در پیش‌بینی رتبه هستند. جالب اینجاست که متغیر sex (جنسیت) هیچ نقشی در این مدل نداشته است.
  • تشخیص بیش‌برازش (Overfitting Diagnosis): با بررسی جدول CP (Complexity Parameter)، مشاهده می‌شود که خطای اعتبارسنجی متقابل (xerror) در ابتدا کاهش می‌یابد و در ۴ تقسیم (nsplit=4) به کمینه خود (۰.۲۹) می‌رسد. اما با پیچیده‌تر شدن درخت (۱۱ تقسیم)، خطا مجدداً افزایش یافته (۰.۳۱) است. این الگوی U شکل در خطا، نشان‌دهنده وقوع Overfitting در مدل کامل است.

2.7 استراتژی هرس کردن درخت (Pruning Strategy)

برای مقابله با بیش‌برازش و رسیدن به یک مدل تعمیم‌پذیر، باید مفاهیم زیر را در نظر بگیریم:

[Image of overfitting underfitting optimal model diagram]

2.7.1 ۱. مفهوم بیش‌برازش و پارامتر پیچیدگی (CP)

یادگیری بیش از حد زمانی رخ می‌دهد که مدل، نویز (Noise) موجود در داده‌های آموزشی را به جای سیگنال (Signal) واقعی یاد می‌گیرد. پارامتر CP مکانیزمی برای جریمه کردن پیچیدگی مدل است؛ هرچه CP کمتر باشد، درخت اجازه دارد شاخ و برگ بیشتری داشته باشد و مستعد Overfitting شود.

2.7.2 ۲. تحلیل جدول CP و انتخاب بهترین مدل

ما برای انتخاب نقطه برش بهینه، به ستون xerror (خطای تخمین زده شده روی داده‌های دیده نشده) نگاه می‌کنیم.

  • روش حداقل خطا (Min Error): کمترین میزان خطا برابر ۰.۵۰۰۰۰ است که در ردیف ۳ (با nsplit = 2) رخ داده است.

  • قانون یک خطای استاندارد (1-SE Rule): این یک رویکرد محافظه‌کارانه است که می‌گوید: «ساده‌ترین مدلی را انتخاب کن که خطای آن تفاوت معناداری با بهترین مدل نداشته باشد.»
    محاسبات:

    • کمترین خطا (Best Error): 0.50000

    • خطای استاندارد (SE): 0.07599

    • آستانه مجاز: \(0.50000 + 0.07599 = 0.57599\)

    نتیجه‌گیری: مدل ردیف ۲ دارای خطای 0.59211 است که از آستانه مجاز (۰.۵۷۵۹۹) بیشتر است. بنابراین، ما همان ردیف ۳ را به عنوان بهینه‌ترین مدل انتخاب می‌کنیم.

2.8 هرس کردن مدل (Pruning)

# مدل هرس شده با cp بهینه
best_cp <- model$cptable[which.min(model$cptable[,"xerror"]), "CP"]
pruned_model <- prune(model, cp = best_cp)
rpart.plot(pruned_model)

ساختار نهایی درخت تصمیم (Pruned Tree Structure):
فرآیند هرس کردن (Pruning) منجر به ایجاد مدلی بسیار شفاف و “تفسیرپذیر” شد. نکته قابل توجه این است که از بین تمام متغیرها، تنها دو متغیر yrs.since.phd و yrs.service برای تعیین رتبه علمی کافی شناخته شدند.

قوانین استخراج شده (Decision Rules):

  • ۱. گره ریشه (Root Node): معیار اصلی تصمیم‌گیری، سابقه دکترا است.
    سوال: آیا yrs.since.phd < 12 است؟
    • خیر (سابقه ≥ ۱۲ سال): فرد مستقیماً به عنوان Prof (استاد تمام) طبقه‌بندی می‌شود. (پوشش اکثریت داده‌ها)
    • بله (سابقه < ۱۲ سال): نیاز به بررسی شرط دوم است.
  • ۲. گره فرزند (Child Node): برای افراد با سابقه دکترای کم، سابقه خدمت بررسی می‌شود.
    سوال: آیا yrs.service >= 6 است؟
    • بله: فرد به عنوان AssocProf (دانشیار) طبقه‌بندی می‌شود.
    • خیر: فرد به عنوان AsstProf (استادیار) طبقه‌بندی می‌شود.

3 ارزیابی مدل

اکنون مدل هرس شده و نهایی خود را بر روی داده‌های تست (که مدل هرگز ندیده) ارزیابی می‌کنیم.

baraz <- predict(pruned_model, test, type = "class")
cm <- confusionMatrix(data = baraz, reference = test$rank)
print(cm)
## Confusion Matrix and Statistics
## 
##            Reference
## Prediction  AssocProf AsstProf Prof
##   AssocProf         4        0    0
##   AsstProf          2       15    0
##   Prof              9        0   60
## 
## Overall Statistics
##                                           
##                Accuracy : 0.8778          
##                  95% CI : (0.7918, 0.9374)
##     No Information Rate : 0.6667          
##     P-Value [Acc > NIR] : 3.922e-06       
##                                           
##                   Kappa : 0.7284          
##                                           
##  Mcnemar's Test P-Value : NA              
## 
## Statistics by Class:
## 
##                      Class: AssocProf Class: AsstProf Class: Prof
## Sensitivity                   0.26667          1.0000      1.0000
## Specificity                   1.00000          0.9733      0.7000
## Pos Pred Value                1.00000          0.8824      0.8696
## Neg Pred Value                0.87209          1.0000      1.0000
## Prevalence                    0.16667          0.1667      0.6667
## Detection Rate                0.04444          0.1667      0.6667
## Detection Prevalence          0.04444          0.1889      0.7667
## Balanced Accuracy             0.63333          0.9867      0.8500

ارزیابی عملکرد مدل بر اساس ماتریس آشفتگی (Confusion Matrix):
این ماتریس نقشه دقیقی از پیش‌بینی‌های درست و نادرست مدل را ارائه می‌دهد. نتایج حاصله به شرح زیر است:

  • دقت کلی (Overall Accuracy): مدل توانست با دقت ۸۷.۸٪ و شاخص کاپای (Kappa) ۰.۷۲۸ عمل کند که نشان‌دهنده عملکردی بسیار فراتر از حدس تصادفی است.
  • نقاط قوت (Strengths): مدل در شناسایی کلاس‌های AsstProf (استادیار) و Prof (استاد تمام) عملکرد بی‌نظیری داشت و به حساسیت (Sensitivity) ۱۰۰٪ دست یافت.
  • نقاط ضعف (Weaknesses): پاشنه آشیل مدل، تشخیص کلاس AssocProf (دانشیار) است. حساسیت در این کلاس تنها ۲۶.۷٪ بود؛ به طوری که ۹ نفر از ۱۵ دانشیار، به اشتباه به عنوان استاد تمام پیش‌بینی شدند.

3.1 تحلیل تکمیلی: منحنی ROC و شاخص AUC

در مسائل طبقه‌بندی چندکلاسه (Multi-class Classification)، برای محاسبه سطح زیر منحنی (AUC)، از رویکرد “یکی در برابر همه” (One-vs-All / OvA) استفاده می‌شود.

اگرچه پکیج caret در خروجی استاندارد خود مقادیر AUC چندکلاسه را گزارش نمی‌کند، اما با توجه به حساسیت (Sensitivity) و ویژگی (Specificity) بسیار بالا در کلاس‌های Prof و AsstProf، می‌توان با اطمینان بالا استنباط کرد که:

  1. شاخص AUC برای کلاس‌های Prof و AsstProf بسیار بالا (احتمالاً > ۰.۹۰) است.
  2. شاخص AUC برای کلاس AssocProf به دلیل خطای تشخیص بالا، متوسط (احتمالاً حدود ۰.۷۹) خواهد بود.

3.2 تحلیل اهمیت متغیرها

importance <- pruned_model$variable.importance
print(importance)
## yrs.since.phd   yrs.service        salary 
##      76.53850      58.76535      35.06974
sorted_importance <- sort(importance)

par(mar = c(5, 7, 4, 2) + 0.1)
barplot(
  sorted_importance,
  main = "اهمیت متغیرها در مدل CART (هرس‌شده)",
  xlab = "اهمیت (Importance)",
  horiz = TRUE,
  las = 1,
  
  col = "darkred"
)

par(mar = c(5, 4, 4, 2) + 0.1)

تفسیر کمی اهمیت متغیرها در درخت تصمیم نهایی:
این نمودار سهم هر متغیر را در فرآیند تصمیم‌گیری درخت (بر اساس میزان کاهش ناخالصی گره‌ها) به صورت عددی نشان می‌دهد:

  • متغیرهای غالب (Dominant Predictors):
    متغیر yrs.since.phd (سال‌های پس از دکترا) با امتیاز قاطع ۷۶.۵، قوی‌ترین عامل در پیش‌بینی رتبه است. پس از آن yrs.service (سابقه خدمت) با امتیاز ۵۸.۸ در رتبه دوم قرار دارد.
  • تطابق و اعتبار مدل:
    این نتایج کاملاً ساختار نهایی مدل هرس‌شده را تأیید می‌کند، زیرا مدل نهایی فقط از همین دو متغیر برای ایجاد تمام قوانین تقسیم‌بندی استفاده کرده است.
  • نقش متغیر حقوق (Salary):
    متغیر salary با امتیاز ۳۵.۱، اهمیت نسبی کمتری را نشان داد. این امتیاز حاکی از آن است که حقوق در مدل پیچیده‌تر و هرس‌نشده حضور داشته، اما برای تعیین قوانین نهایی به اندازه متغیرهای سابقه، کلیدی نبوده است.
  • متغیرهای کم‌اهمیت:
    متغیرهای discipline و sex به دلیل اهمیت ناچیز، در هیچ یک از قوانین تقسیم‌بندی مدل نهایی استفاده نشدند.

4 مقایسه با مدل جنگل تصادفی

set.seed(38712)
rf_model <- randomForest(
  rank ~ .,
  data = train,
  ntree = 200,
  importance = TRUE
)
print(rf_model)
## 
## Call:
##  randomForest(formula = rank ~ ., data = train, ntree = 200, importance = TRUE) 
##                Type of random forest: classification
##                      Number of trees: 200
## No. of variables tried at each split: 2
## 
##         OOB estimate of  error rate: 9.09%
## Confusion matrix:
##           AssocProf AsstProf Prof class.error
## AssocProf        29        2   16  0.38297872
## AsstProf          3       43    0  0.06521739
## Prof              4        0  178  0.02197802
rf_predictions <- predict(rf_model, test, type = "class")
cm_rf <- confusionMatrix(data = rf_predictions, reference = test$rank)
print(cm_rf)
## Confusion Matrix and Statistics
## 
##            Reference
## Prediction  AssocProf AsstProf Prof
##   AssocProf         6        0    0
##   AsstProf          0       15    0
##   Prof              9        0   60
## 
## Overall Statistics
##                                           
##                Accuracy : 0.9             
##                  95% CI : (0.8186, 0.9532)
##     No Information Rate : 0.6667          
##     P-Value [Acc > NIR] : 2.485e-07       
##                                           
##                   Kappa : 0.7778          
##                                           
##  Mcnemar's Test P-Value : NA              
## 
## Statistics by Class:
## 
##                      Class: AssocProf Class: AsstProf Class: Prof
## Sensitivity                   0.40000          1.0000      1.0000
## Specificity                   1.00000          1.0000      0.7000
## Pos Pred Value                1.00000          1.0000      0.8696
## Neg Pred Value                0.89286          1.0000      1.0000
## Prevalence                    0.16667          0.1667      0.6667
## Detection Rate                0.06667          0.1667      0.6667
## Detection Prevalence          0.06667          0.1667      0.7667
## Balanced Accuracy             0.70000          1.0000      0.8500
accuracy_cart <- cm$overall["Accuracy"]
accuracy_rf <- cm_rf$overall["Accuracy"]

print(paste("دقت مدل درخت تصمیم (CART):", round(accuracy_cart, 4)))
## [1] "دقت مدل درخت تصمیم (CART): 0.8778"
print(paste("دقت مدل جنگل تصادفی (RF):", round(accuracy_rf, 4)))
## [1] "دقت مدل جنگل تصادفی (RF): 0.9"
varImpPlot(rf_model, main = "اهمیت متغیرها در مدل (Random Forest)")

تحلیل تطبیقی: درخت تصمیم (CART) در برابر جنگل تصادفی (Random Forest):
مدل Random Forest به عنوان یک روش Ensemble (گروهی) که از تجمیع آراء صدها درخت تصمیم استفاده می‌کند، تفاوت‌های عملکردی زیر را با مدل تک‌درختی نشان داد:

  • مزایای Random Forest:
    • کاهش Overfitting از طریق میانگین‌گیری پیش‌بینی‌های چندین درخت.
    • مقاومت بالاتر در برابر نویز و داده‌های پرت.
    • دقت پیش‌بینی بالاتر (افزایش دقت از ۸۷.۸٪ به ۹۰٪ در این تحلیل).
  • مزایای CART (درخت تصمیم ساده):
    • تفسیرپذیری کامل (Interpretability): قوانین به صورت “اگر-آنگاه” کاملاً شفاف هستند.
    • سرعت آموزش و پیش‌بینی بسیار بالا.
    • مناسب برای ارائه به ذینفعان غیرفنی.

نکته: نمودار اهمیت متغیرها در هر دو مدل یکسان بود و yrs.since.phd و yrs.service را به عنوان عوامل اصلی شناسایی کرد که اعتبار تحلیل را تایید می‌کند.

5 نتیجه‌گیری و پیشنهادات

خلاصه یافته‌های کلیدی:

  1. عوامل تعیین‌کننده: متغیرهای سابقه دکترا (yrs.since.phd) و سابقه خدمت (yrs.service) قوی‌ترین پیش‌بینی‌کننده‌های رتبه آکادمیک هستند. متغیرهای جنسیت و رشته تأثیر معناداری نداشتند.
  2. ارزیابی عملکرد: مدل درخت تصمیم هرس‌شده با دقت ۸۷.۸٪ عملکرد قابل قبولی دارد. با این حال، پاشنه آشیل مدل، تشخیص کلاس AssocProf (دانشیار) است که اغلب با استاد تمام اشتباه گرفته می‌شود.
  3. شفافیت مدل: مدل نهایی به طرز شگفت‌انگیزی ساده شد و تنها با ۲ قانون تصمیم‌گیری توانست اکثریت داده‌ها را به درستی طبقه‌بندی کند.

مسیرهای بهبود در آینده (Future Work):

  • جمع‌آوری داده‌های بیشتر (Over-sampling) برای کلاس AssocProf جهت رفع عدم توازن.
  • مهندسی ویژگی (Feature Engineering): افزودن ستون‌هایی مانند “تعداد مقالات”، “h-index” یا “گرنت‌های دریافتی” برای تمایز بهتر بین رتبه‌های علمی.
  • استفاده از روش‌های Boosting (مانند XGBoost) اگر اولویت با دقت مدل است و تفسیرپذیری اهمیت کمتری دارد.

5.0.1 چند نکته فراتر

theme_set(theme_minimal())

p_rank <- ggplot(mis, aes(x = rank, fill = rank)) +
  geom_bar() +
  labs(title = "توزیع رتبه (Rank)")

p_disc <- ggplot(mis, aes(x = discipline, fill = discipline)) +
  geom_bar() +
  labs(title = "توزیع رشته (Discipline)")

p_sex <- ggplot(mis, aes(x = sex, fill = sex)) +
  geom_bar() +
  labs(title = "توزیع جنسیت (Sex)")

(p_rank | p_disc | p_sex)

p_phd_hist <- ggplot(mis, aes(x = yrs.since.phd)) +
  geom_histogram(bins = 20, fill = "skyblue", color = "black") +
  labs(title = "توزیع سال‌های پس از دکترا", x = "Yrs. Since PhD")

p_serv_hist <- ggplot(mis, aes(x = yrs.service)) +
  geom_histogram(bins = 20, fill = "salmon", color = "black") +
  labs(title = "توزیع سابقه خدمت", x = "Yrs. Service")

p_sal_hist <- ggplot(mis, aes(x = salary)) +
  geom_histogram(bins = 30, fill = "lightgreen", color = "black") +
  labs(title = "توزیع حقوق", x = "Salary")

(p_phd_hist | p_serv_hist) / (p_sal_hist)

p_phd_box <- ggplot(mis, aes(y = yrs.since.phd)) +
  geom_boxplot(fill = "skyblue") +
  labs(title = "باکس پلات سال‌های پس از دکترا") +
  theme(axis.text.x = element_blank(), axis.ticks.x = element_blank())

p_serv_box <- ggplot(mis, aes(y = yrs.service)) +
  geom_boxplot(fill = "salmon") +
  labs(title = "باکس پلات سابقه خدمت") +
  theme(axis.text.x = element_blank(), axis.ticks.x = element_blank())

p_sal_box <- ggplot(mis, aes(y = salary)) +
  geom_boxplot(fill = "lightgreen") +
  labs(title = "باکس پلات حقوق") +
  theme(axis.text.x = element_blank(), axis.ticks.x = element_blank())

(p_phd_box | p_serv_box | p_sal_box)

p_rank_sal_box <- ggplot(mis, aes(x = rank, y = salary, fill = rank)) +
  geom_boxplot() +
  labs(title = "رابطه حقوق و رتبه (Salary by Rank)", x = "Rank", y = "Salary") +
  theme(legend.position = "none")

print(p_rank_sal_box)

rf_imp <- as.data.frame(importance(rf_model))
rf_imp$Variable <- rownames(rf_imp)


ggplot(rf_imp, aes(x = MeanDecreaseGini, y = fct_reorder(Variable, MeanDecreaseGini))) +
  geom_col(fill = "steelblue") +
  labs(
    title = "اهمیت متغیرها در مدل (Random Forest)",
    x = "اهمیت (MeanDecreaseGini)",
    y = "متغیر"
  ) +
  theme_minimal()

par(mfrow = c(1, 2), mar = c(5, 4, 4, 2) + 0.1)

boxplot(yrs.since.phd ~ rank, 
        data = mis, 
        main = "سابقه دکترا بر اساس رتبه",
        xlab = "رتبه (Rank)",
        ylab = "سال‌های پس از دکترا",
        col = c("#0a9396", "#ee9b00", "#005f73"))

boxplot(yrs.service ~ rank, 
        data = mis, 
        main = "سابقه خدمت بر اساس رتبه",
        xlab = "رتبه (Rank)",
        ylab = "سال‌های خدمت",
        col = c("#0a9396", "#ee9b00", "#005f73"))

par(mfrow = c(1, 1))

5.0.2 نتیجه‌گیری نهایی

خلاصه مدیریتی و دستاوردهای تحلیل:

در این پروژه، مدلی موفق برای پیش‌بینی رتبه اعضای هیئت علمی توسعه یافت. نتایج به شرح زیر است:

  • ۱. کشف الگوهای پنهان: تحلیل‌ها اثبات کرد که متغیرهای زمانی، به‌ویژه yrs.since.phd (سال‌های پس از دکترا) و yrs.service (سابقه خدمت)، قوی‌ترین پیش‌بینی‌کننده‌ها هستند. در مقابل، متغیرهای دموگرافیک مانند رشته (Discipline) و جنسیت (Sex) تأثیر ناچیزی در تعیین رتبه داشتند.
  • ۲. تعادل بین دقت و تفسیرپذیری:
    • مدل درخت تصمیم (CART): با وجود سادگی فوق‌العاده (تنها ۲ قانون)، به دقت قابل قبول ۸۷.۸٪ دست یافت که برای تصمیم‌گیری‌های شفاف مدیریتی ایده‌آل است.
    • مدل جنگل تصادفی (Random Forest): با پیچیدگی بیشتر، دقت را به ۹۰.۰٪ ارتقا داد که اعتبار متغیرهای انتخابی را تایید می‌کند.
  • ۳. چالش اصلی (The Bottleneck): پاشنه آشیل هر دو مدل، تشخیص رتبه «دانشیار» (AssocProf) بود. مدل CART تنها ۲۶.۷٪ و مدل RF حدود ۴۰٪ از دانشیاران را درست تشخیص دادند. این نشان می‌دهد که مرز بین “دانشیار” و “استاد تمام” صرفاً با سنوات خدمت قابل تفکیک نیست.

پیشنهاد استراتژیک:

برای بهبود مدل در فازهای بعدی، پیشنهاد می‌شود علاوه بر جمع‌آوری داده‌های بیشتر برای کلاس دانشیار، از شاخص‌های عملکردی (مانند تعداد مقالات، شاخص h-index و حجم گرنت‌های پژوهشی) به عنوان متغیرهای ورودی استفاده شود.